package com.moro.lisp.typedefine;



import com.moro.lisp.JLispData;
import com.moro.lisp.JLispType;
import com.moro.lisp.closure.Action;
import com.moro.lisp.os.Terminal;
import com.moro.lisp.tools.JLispStack;
import com.moro.lisp.tools.SymbolPool;
import com.moro.lisp.typedefine.Error;

public class Atom {
	/*
	 * 这个字段表示该原子字面上的值，用Java中的String类型表示
	 * 注意这个原子的值不能被改变，并且也不能再创建有相同值的原子（被捕获）
	 * 一个原子A对应的val值就是"A"
	 */
	public String name;
	
	
	
	/*
	 * 这个字段表示该原子是不是数字
	 */
	public boolean isNumber;
	
	
	
	
	/*
	 * 这个字段存储的是该原子作为变量时所存储的一般值，并使用栈类型存储，因为一个变量在不同作用域时有不同的一般值，对应的操作就是值入栈和值出栈
	 */
	public JLispStack symbolValues;
	
	
	
	
	/*
	 * 这个字段存储的是该原子作为变量时所存储的函数值，使用JavaLisp数据存储(单个)，因为一个变量的函数值是不存在作用域之分的，它只有单个的值，并且也
	 * 不会像一般值那样被捕获进函数里面，意思就是函数值改变了就是改变了，是不可恢复的
	 */
	private JLispData symbolFunction;//为什么要用JLispData而不用Function，因为符号的函数值可以储存函数还有宏，只能存储其中一种
	
	
	
	/*
	 * 这个字段表示该原子是不是专属于闭包中的原子
	 */
	public Action isClosureAtom;
	
	
	public Atom(String name) {
		this.name = name;
		if(isSpecial(name)) {
			this.symbolValues = null;
			
			this.symbolFunction = null;
			
			this.isClosureAtom = null;//默认不是闭包中的原子
		}else {
			this.symbolValues = new JLispStack(this);
			
			this.symbolFunction = null;
			
			this.isClosureAtom = null;//默认不是闭包中的原子
		}
	}
	private boolean isSpecial(String name) {//根据名字判断是不是特殊原子，好决定要不要赋值值栈
		if("t".equalsIgnoreCase(name)||"nil".equalsIgnoreCase(name)||"&rest".equalsIgnoreCase(name)) {
			this.isNumber = false;//不是数字原子
			return true;
		}else {
			this.isNumber = name.matches("[-]?[0-9]*[.]?[0-9]*");//???待完善
			return this.isNumber;
		}
	}
	
	/*public static void main(String[] args) {
		System.out.println("09.9.9".matches("[0-9]+[.]?[0-9]+"));
	}*/
	/*
	 * 这个方法主要给符号赋值，注意必须在一块新的作用域中赋值才能用到此方法，否则那就是重新设置当前值
	 */
	public void setValue(JLispData value) {
		if(null == this.symbolValues) {//如果这个原子没有值栈，比如t,nil,12等对自身求值的原子，则不做任何操作
			return;
		}
		if(null == value) {
			this.symbolValues.push(null);
			return;
		}
		if(value.type == JLispType.FUNCTION) {
			if(null == this.isClosureAtom) {
				((Function)(value.data)).asSymbolValue.add(this);
			}
			
		}else if(value.type == JLispType.MACRO) {
			new Error("The macro can not be symbol's general value");
			return;
		}
		this.symbolValues.push(value);
		
	}
	public void pop() {
		if(null == this.symbolValues || this.symbolValues.getSize() == 0) {//如果这个原子没有值栈，比如t,nil,12等对自身求值的原子，则不做任何操作
			return;
		}
		if(null == this.symbolValues.now()) {
			this.symbolValues.pop();
			return;
		}
		if(this.symbolValues.now().type == JLispType.FUNCTION) {
			if(null == this.isClosureAtom) {
				((Function)(this.symbolValues.now().data)).asSymbolValue.remove(this);
			}
			
		}
		this.symbolValues.pop();
	}
	
	/*
	 * 给符号的当前作用域重新赋值
	 */
	public void resetValue(JLispData value) {
		if(null != this.isClosureAtom) {
			//Terminal.print(value);
			this.isClosureAtom.setValue(value);
			this.symbolValues.resetVal(this.isClosureAtom.value);
			return;
		}
		if(null == this.symbolValues || this.symbolValues.getSize() == 0) {//如果这个原子没有值栈，比如t,nil,12等对自身求值的原子，则不做任何操作
			return;
		}
		
		if(value.type == JLispType.MACRO) {//如果值是Macro则直接返回不作任何操作
			new Error("The macro can not be symbol's general value");
			return;
		}
		if(null == this.symbolValues.now()) {
			if(value.type == JLispType.FUNCTION) {
				((Function)(value.data)).asSymbolValue.add(this);
			}
			this.symbolValues.resetVal(value);
			return;
		}
		if(this.symbolValues.now().type == JLispType.FUNCTION) {
			((Function)(this.symbolValues.now().data)).asSymbolValue.remove(this);
		}
		if(value.type == JLispType.FUNCTION) {
			((Function)(value.data)).asSymbolValue.add(this);
		}
		this.symbolValues.resetVal(value);
	}
	
	public JLispData eval() {//对原子求值不需要符号池
		if(null == this.symbolValues) {//对于没有值栈的原子，（对自身求值的原子）返回它们自己
			return new JLispData(this,JLispType.ATOM);
		}
		JLispData data = this.symbolValues.now();
		if(null == data) {
			return new JLispData(new Error("The Symbol \""+this.name+"\" has no general value"),JLispType.ERROR);
		}
		return data;
	}	
	public void setFunctionVal(JLispData symbolFunction) {
		if(null == this.symbolValues) {//对于没有值栈的原子，则不做任何操作，如果一个原子没有值栈，那么它也不能有函数值
			return;
		}
		if(null == this.symbolFunction) {
			
			if(JLispType.FUNCTION == symbolFunction.type) {
				//System.out.println(((Function)(symbolFunction.data))/*.asSymbolFunction*/);
				((Function)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else if(JLispType.MACRO == symbolFunction.type) {
				((Macro)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else {
				return;
			}
		}else {
			if(JLispType.FUNCTION == this.symbolFunction.type && JLispType.FUNCTION == symbolFunction.type) {
				((Function)(this.symbolFunction.data)).asSymbolFunction.remove(this);
				((Function)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else if(JLispType.MACRO == this.symbolFunction.type && JLispType.MACRO == symbolFunction.type) {
				((Macro)(this.symbolFunction.data)).asSymbolFunction.remove(this);
				((Macro)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else if(JLispType.FUNCTION == this.symbolFunction.type && JLispType.MACRO == symbolFunction.type) {
				((Function)(this.symbolFunction.data)).asSymbolFunction.remove(this);
				((Macro)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else if(JLispType.MACRO == this.symbolFunction.type && JLispType.FUNCTION == symbolFunction.type) {
				((Macro)(this.symbolFunction.data)).asSymbolFunction.remove(this);
				((Function)(symbolFunction.data)).asSymbolFunction.add(this);
				this.symbolFunction = symbolFunction;
			}else {
				return;
			}
		}
	}
	
	
	public JLispData functionEval() {
		return this.symbolFunction;
	}
}
